
#ifndef __LIBERTY_ENGINE_COROUTINE_H__
#define __LIBERTY_ENGINE_COROUTINE_H__

#include <memory>
#include <string>

#include <Liberty3D/Liberty3D.h>

#include <Liberty3D/Engine/IOperation.h>

#include <Liberty3D/Engine/Object.h>
#include <Liberty3D/Engine/Performance.h>
#include <Liberty3D/Engine/YieldInstruction.h>

#include <boost/any.hpp>

namespace Liberty { namespace Engine {
    enum CoroutineStatus {
        READY,
        WAIT_FOR_OPERATION,
        WAIT_FOR_END_OF_FRAME,
        WAIT_FOR_FIXED_UPDATE,
        WAIT_FOR_SECONDS,
        DONE
    };

    enum CoroutineType {
        COROUTINE,
        INVOKE
    };

    class Coroutine : public IOperation, public YieldInstruction {
    public:
        virtual boost::any tick() = 0;
    };
    
    class CoroutineEntry {
    protected:
        std::shared_ptr<Coroutine>  _coroutine;
        std::shared_ptr<Object>     _object;
        std::string                 _name;
        CoroutineType               _type;
        CoroutineStatus             _status;
        std::shared_ptr<IOperation> _operation;
        Performance::Counter        _until;

    public:
        CoroutineEntry(CoroutineType t, const std::shared_ptr<Object>& o, const std::string& n);

    public:
        bool ready(const Performance::Counter& currentTime) const;
        bool tick (const Performance::Counter& currentTime);

    public:
        inline CoroutineStatus status() const { return _status; }
    };
}}

#endif
